package team.chess.control;


import team.chess.client.Client;
import team.chess.client.JoinRoom;
import team.chess.qieces.*;
import team.chess.server.CreateRoom;
import team.chess.server.Server;
import team.chess.ui.CheckerBoard;
import team.chess.util.Request;
import team.chess.util.Response;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.net.Socket;
import java.util.Arrays;


public class MyPanel extends JPanel {

    //提示窗1.执棋方提示 2.红方被将军 3.黑方被将军
    JLabel label_1 = new JLabel("红方执棋");
    JLabel label_2 = new JLabel("红方被将军");
    JLabel label_3 = new JLabel("黑方被将军");
    JLabel label_4 = new JLabel("黑将被将，别乱走");
    JLabel label_5 = new JLabel("红将被将，别乱走");
    JButton button = new JButton("悔棋");

    //用于判断回合所属者
    int index = 1;

    //存上一步的棋子的kind值，用于swap_1的吃子悔棋
    int k;
    int k2;

    //判断可否悔棋 1.不可悔棋 2.可以悔棋
    int retry = 1;

    //被将军方 0.没有将军 1.红被将 2.黑被将
    int checkmate = 0;

    //棋子创建
    Qiece[] qieces = new Qiece[0];

    //背景构建
    CheckerBoard board = new CheckerBoard();

    Server server = null;
    Client client = null;

    InputStream serveris = null;
    ObjectInputStream serverois= null;

    InputStream clientis = null;
    ObjectInputStream clientois= null;

    public MyPanel(){
        Init();
    }

    public MyPanel(Server server){
        this.server = server;
        new Thread(){
            @Override
            public void run() {
                try {
//                    try {
//                        sleep(10000);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
                    while (true){
                        try {
                            sleep(10000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        Response response = new Response(qieces);
                        for(int i=0;i<10;i++){
                            for (int j=0;j<9;j++) {
                                System.out.print(i*9+j + "," + qieces[i*9+j].getKind() + "," + qieces[i*9+j].getMoveof() + "," + qieces[i*9+j].getScl() + "<" + qieces[i*9+j].getX() + "," + qieces[i*9+j].getY() + "> \t");
                            }
                            System.out.println();
                        }
                        server.send(response);

                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }.start();

        new Thread(){
            @Override
            public void run() {
                try {
                    serveris = server.socket.getInputStream();
                    serverois = new ObjectInputStream(serveris);
                    while (true){

                        Request request= (Request) serverois.readObject();
                        if (request!=null){
                            System.out.println("收到信息");
                            System.out.println("A:"+request.getA()+" B:"+request.getB()+" C:"+request.getI()+" D:"+request.getJ());
                            moveSelected(request.getA(),request.getB(),request.getI(),request.getJ());
                            index = 1-index;
                            if (index == 0){
                                label_1.setText("黑方执棋");
                            }else if (index == 1){
                                label_1.setText("红方执棋");
                            }
                            repaint();
                        }

                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }.start();
        Init();
    }

    public MyPanel(Client client){

        this.client = client;
        new Thread(){
            @Override
            public void run() {
                try {
                    clientis= client.socket.getInputStream();
                    clientois=new ObjectInputStream(clientis);
                    System.out.println("等待收消息");
                    while (true){
                        Response response = (Response) clientois.readObject();
                        System.out.println("收到消息");
                        qieces = response.getQieces();
                        repaint();
                        try {
                            System.out.println("开始暂停");
                            sleep(100);

                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }.start();
        Init();
    }


    public void Init(){
        this.setLayout(null);
        label_1.setBounds(980,200,150,50);
        label_1.setFont(new Font("楷体",Font.BOLD,24));
        this.add(label_1);
        label_1.setVisible(true);

        label_2.setBounds(980,200,150,50);
        label_2.setFont(new Font("楷体",Font.BOLD,24));
        this.add(label_2);
        label_2.setVisible(false);

        label_3.setBounds(980,200,150,50);
        label_3.setFont(new Font("楷体",Font.BOLD,24));
        this.add(label_3);
        label_3.setVisible(false);

        label_4.setBounds(950,200,200,50);
        label_4.setFont(new Font("楷体",Font.BOLD,24));
        this.add(label_4);
        label_4.setVisible(false);

        label_5.setBounds(950,200,200,50);
        label_5.setFont(new Font("楷体",Font.BOLD,24));
        this.add(label_5);
        label_5.setVisible(false);

        button.setBounds(940,600,200,50);
        button.setFont(new Font("楷体",Font.BOLD,24));
        this.add(button);
        button.setVisible(true);

        CreatQieces();
        mouseAction();
        clicked();
    }

    int x1,y1,x2,y2;

    public void clicked(){
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (retry == 0){
                    System.out.println("触发悔棋");
                    if (k == 0) {
                        swap(x1,y1,x2,y2);
                    } else {
                        swap_1(x1,y1,x2,y2);
                        qieces[x1 * 9 + y1].setController(index);
                        qieces[x2 * 9 + y2].setController(1 - index);
                    }
                    index = 1 - index;
                    if (index == 0){
                        label_1.setText("黑方执棋");
                    }else if (index == 1){
                        label_1.setText("红方执棋");
                    }
                    t=0;
                    retry = 1;
                }
                for (int num = 0; num < 90; num++) {
                    qieces[num].setMoveof(0);
                    qieces[num].setScl(0);
                }
                repaint();
            }
        });
    }


    //贴图绘制
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        board.paintSelf(g);
        for (Qiece q:qieces){
            q.paintSelf(g);
        }
    }


    //鼠标点击事件（返回点击坐标）
    //t用于区分第一次和第二次点击
    //x,y为本次点击的坐标
    //i,j上一次点击的行列值
    //A,B本次点击的行列值
    int x,y,t,i,j,A,B;
    public void mouseAction(){
        MouseAdapter mouse = new MouseAdapter(){
            @Override
            public void mousePressed(MouseEvent e){
//                retry = 1;

                //黑方执棋
                if(e.getButton()==MouseEvent.BUTTON1 && index == 0){
                    System.out.println("a");

                    //读取鼠标点击的位置
                    x = e.getX();
                    y = e.getY();
                    int X=(y-20)/90;
                    int Y=(x-62)/90;

                    if (t == 0 && qieces[X*9+Y].getController() != index){
                        return;
                    }

                    if (t == 0 && qieces[X*9+Y].getController() != index){
                        System.out.println("c");
                        return;
                    }

                    if (t == 1 && qieces[X*9+Y].getController() == qieces[i*9+j].getController() && qieces[X*9+Y].getKind() != 0){
                        t=0;
                        qieces[X*9+Y].setScl(0);
                        for (int num = 0; num<90; num++){
                            qieces[num].setMoveof(0);
                        }
                    }else if (t == 1 && qieces[X*9+Y].getController() != qieces[i*9+j].getController() && qieces[X*9+Y].getKind() != 0 && qieces[X*9+Y].getMoveof() == 0){
                        System.out.println("d");
                        return;
                    }

                    //对一个棋子的选取操作
                    if(selectOf(x,y) && t==0 && qieces[X*9+Y].getController() == index){
                        t=1;
                        i=X;
                        j=Y;
//                        for(int i=0;i<10;i++){
//                            for (int j=0;j<9;j++) {
//                                System.out.print(i*9+j + "," + qieces[i*9+j].getKind() + "," + qieces[i*9+j].getMoveof() + "," + qieces[i*9+j].getScl() + "<" + qieces[i*9+j].getX() + "," + qieces[i*9+j].getY() + "> \t");
//                            }
//                            System.out.println();
//                        }

                        repaint();
                        return;
                    }

                    if (t==1 && qieces[X*9+Y].getMoveof() == 0){
                        System.out.println("e");
                        return;
                    }

                    //对选取棋子的移动操作
                    if(t==1 && qieces[X*9+Y].getMoveof() == 1){
                        k=qieces[X*9+Y].getKind();

                        k=qieces[X*9+Y].getKind();
                        if (client==null){
                            System.out.println("A:"+X+" B:"+Y+" C:"+i+" D:"+j);
                            moveSelected(X,Y,i,j);
                        }else{
                            moveSelected(X,Y,i,j);
                            System.out.println(X+Y+i+j);
                            client.send(new Request(X,Y,i,j));
                        }
                        checkMate();
                        for (int num = 0; num<90; num++){
                            qieces[num].setMoveof(0);
                            qieces[num].setScl(0);
                        }
                        if (checkmate == 2){
                            if (k == 0){
                                swap(i,j,X,Y);
                            }else {
                                swap_1(X,Y,i,j);
                            }
                            k = k2;
                            repaint();
                            return;
                        }

                        A=X;
                        B=Y;
                        retry = 0;
                        x1=A;
                        y1=B;
                        x2=i;
                        y2=j;
                        t=0;
                        k2=k;
                        index = 1;
                        label_1.setText("红方执棋");
                        //重画
                        repaint();
                    }

                }

                //红方执棋
                else if(e.getButton()==MouseEvent.BUTTON1 && index == 1){
                    System.out.println("b");
                    //读取鼠标点击的位置
                    x = e.getX();
                    y = e.getY();
                    int X=(y-20)/90;
                    int Y=(x-62)/90;

                    if (t == 0 && qieces[X*9+Y].getController() != index){
                        return;
                    }



                    if (qieces[X*9+Y].getController() != index && t == 0){
                        return;
                    }

                    if (t == 1 && qieces[X*9+Y].getController() == qieces[i*9+j].getController() && qieces[X*9+Y].getKind() != 0){
                        t=0;
                        qieces[X*9+Y].setScl(0);
                        for (int num = 0; num<90; num++){
                            qieces[num].setMoveof(0);
                        }
                    }else if (t == 1 && qieces[X*9+Y].getController() != qieces[i*9+j].getController() && qieces[X*9+Y].getKind() != 0 && qieces[X*9+Y].getMoveof() == 0){
                        return;
                    }

                    //对一个棋子的选取操作
                    if(selectOf(x,y) && t==0 && qieces[X*9+Y].getController() == index){
                        t=1;
                        i=X;
                        j=Y;
//                        for(int i=0;i<10;i++){
//                            for (int j=0;j<9;j++) {
//                                System.out.print(i*9+j + "," + qieces[i*9+j].getKind() + "," + qieces[i*9+j].getMoveof() + "," + qieces[i*9+j].getScl() + "<" + qieces[i*9+j].getX() + "," + qieces[i*9+j].getY() + "> \t");
//                            }
//                            System.out.println();
//                        }

                        repaint();

                        return;
                    }

                    if (t==1 && qieces[X*9+Y].getMoveof() == 0){
                        return;
                    }

                    //对选取棋子的移动操作
                    if(t==1 && qieces[X*9+Y].getMoveof() == 1){
                        k=qieces[X*9+Y].getKind();
                        if (client==null){
                            System.out.println("A:"+X+" B:"+Y+" C:"+i+" D:"+j);
                            moveSelected(X,Y,i,j);

                        }else{
                            moveSelected(X,Y,i,j);
                            System.out.println("A:"+X+" B:"+Y+" C:"+i+" D:"+j);
                            client.send(new Request(X,Y,i,j));
                        }
                        checkMate();
                        for (int num = 0; num<90; num++){
                            qieces[num].setMoveof(0);
                            qieces[num].setScl(0);
                        }
                        if (checkmate == 1){
                            if (k == 0){
                                swap(i,j,X,Y);
                            }else {
                                swap_1(X,Y,i,j);
                            }
                            k=k2;
                            repaint();
                            return;
                        }
                        A=X;
                        B=Y;
                        retry = 0;
                        x1=A;
                        y1=B;
                        x2=i;
                        y2=j;
                        k2 = k;
                        t=0;
                        index = 0;
                        label_1.setText("黑方执棋");
                        //重画
                        repaint();
                    }

                }

                //可视化输出90个棋子的底层数据
//                for(int i=0;i<10;i++){
//                    for (int j=0;j<9;j++) {
//                        System.out.print(i*9+j + "," + qieces[i*9+j].getKind() + "," + qieces[i*9+j].getMoveof() + "," + qieces[i*9+j].getScl() + "<" + qieces[i*9+j].getX() + "," + qieces[i*9+j].getY() + "> \t");
//                    }
//                    System.out.println();
//                }

                //输出点击点坐标
                System.out.println(i+","+j);
                System.out.println();
            }
        };
        this.addMouseListener(mouse);
        this.setFocusable(true);
    }


    //初始化棋盘上90个棋子
    public void CreatQieces(){
        //将90个可移动地块置为死棋类
        for (int i = 0; i < 10; i++){
            for (int j = 0; j < 9; j++){
                Qiece o = new Death(i+1,j+1);
                qieces = Arrays.copyOf(qieces,qieces.length + 1);
                qieces[qieces.length - 1] = o;
            }
        }

        //将
        qieces[4] = new General(qieces[4], 0, 0);
        qieces[85] = new General(qieces[85], 0, 1);

        //卒
        for (int i = 0; i < 5; i++) {
            qieces[27 + i * 2] = new Soldier(qieces[27 + i * 2], 0, 0);
            qieces[54 + i * 2] = new Soldier(qieces[54 + i * 2], 0, 1);
        }

        for (int i = 0; i < 2; i++) {
            //车
            qieces[0+i*8] = new Chariot(qieces[0+i*8],0,0);
            qieces[81+i*8] = new Chariot(qieces[81+i*8],0,1);
            //马
            qieces[1+i*6] = new Horse(qieces[1+i*6], 0, 0);
            qieces[82+i*6] = new Horse(qieces[82+i*6], 0, 1);
            //炮
            qieces[19+i*6] = new Cannon(qieces[19+i*6], 0, 0);
            qieces[64+i*6] = new Cannon(qieces[64+i*6], 0, 1);
            //相
            qieces[2+i*4] = new Minister(qieces[2+i*4], 0, 0);
            qieces[83+i*4] = new Minister(qieces[83+i*4], 0, 1);
            //士
            qieces[3+i*2] = new Assistant(qieces[3+i*2], 0, 0);
            qieces[84+i*2] = new Assistant(qieces[84+i*2], 0, 1);
        }

    }

    //通过遍历所有棋子，判断是否有棋子的位置与鼠标点击实践坐标重合
    public boolean selectOf(int x,int y){
        int i=(y-20)/90;            //范围大于图片范围，需修改！！！！！！！
        int j=(x-62)/90;
        if (qieces[i * 9 + j].getController() == index){
            if (qieces[i * 9 + j].select(x, y)) {
                qieces[i * 9 + j].movingRange(qieces, i, j);
                return true;
            }
        }
        return false;
    }

    //通过遍历所有棋子，对已选择的棋子进行移动
    //A,B为第二次点击的行列值；i,j为第一次点击的行列值
    public void moveSelected(int A,int B,int i,int j){

        Qiece o = new Death(i+1,j+1);
        int a = qieces[A*9+B].getX();
        int b = qieces[A*9+B].getY();
        switch (qieces[i*9+j].getKind()){
            case 1 : {
                o = new General(qieces[i*9+j],0,qieces[i*9+j].getController());
                break;
            }
            case 2 : {
                o = new Assistant(qieces[i*9+j],0,qieces[i*9+j].getController());
                break;
            }
            case 3 : {
                o = new Minister(qieces[i*9+j],0,qieces[i*9+j].getController());
                break;
            }
            case 4 : {
                o = new Chariot(qieces[i*9+j],0,qieces[i*9+j].getController());
                break;
            }
            case 5 : {
                o = new Horse(qieces[i*9+j],0,qieces[i*9+j].getController());
                break;
            }
            case 6 : {
                o = new Cannon(qieces[i*9+j],0,qieces[i*9+j].getController());
                break;
            }
            case 7 : {
                o = new Soldier(qieces[i*9+j],0,qieces[i*9+j].getController());
                break;
            }
            default: {
                o = new Death(i, j);
            }
        }
        o.setX(a);
        o.setY(b);

        Qiece o2 = new Death(A+1,B+1);
        a = qieces[i*9+j].getX();
        b = qieces[i*9+j].getY();
        o2.setX(a);
        o2.setY(b);

        qieces[A*9+B] = o;
        qieces[i*9+j] = o2;

        for (int num = 0; num < 90; num++) {
            qieces[num].setMoveof(0);
            qieces[num].setScl(0);
        }

    }


    //判断是否存在将军
    public void checkMate(){
        if (this.index == 0) {                  //黑方
            System.out.println("a");
            for (int num = 0; num < 90; num++){
                if (qieces[num].getController() == 1){
                    qieces[num].movingRange(qieces,num/9,num%9);
                }
            }
            for (int num = 0; num < 90; num++){
                if (qieces[num].getKind() == 1 && qieces[num].getController() == 0 && qieces[num].getMoveof() == 1){//黑
                    System.out.println("d");
                    qieces[num].setMoveof(0);
                    qieces[num].setScl(0);
                    label_1.setVisible(false);
                    label_2.setVisible(false);
                    label_3.setVisible(false);
                    label_4.setVisible(true);
                    label_5.setVisible(false);
                    checkmate = 2;
                    return;
                }
            }
            for (int num = 0; num < 90; num++){
                if (qieces[num].getController() == 0){
                    qieces[num].movingRange(qieces,num/9,num%9);
                }
            }
            for (int num = 0; num < 90; num++){
                if (qieces[num].getKind() == 1 && qieces[num].getController() == 1 && qieces[num].getMoveof() == 1){//红
                    label_1.setVisible(false);
                    label_2.setVisible(true);
                    label_3.setVisible(false);
                    label_4.setVisible(false);
                    label_5.setVisible(false);
                    checkmate = 1;
                    return;
                }
            }
        }else if (this.index == 1){             //红方
            System.out.println("b");
            for (int num = 0; num < 90; num++){
                if (qieces[num].getController() == 0){
                    qieces[num].movingRange(qieces,num/9,num%9);
                }
            }
            for (int num = 0; num < 90; num++){
                if (qieces[num].getKind() == 1 && qieces[num].getController() == 1 && qieces[num].getMoveof() == 1){//红
                    label_1.setVisible(false);
                    label_2.setVisible(false);
                    label_3.setVisible(false);
                    label_4.setVisible(false);
                    label_5.setVisible(true);
                    checkmate = 1;
                    return;
                }
            }
            for (int num = 0; num < 90; num++){
                if (qieces[num].getController() == 1){
                    qieces[num].movingRange(qieces,num/9,num%9);
                }
            }
            for (int num = 0; num < 90; num++){
                if (qieces[num].getKind() == 1 && qieces[num].getController() == 0 && qieces[num].getMoveof() == 1){//黑
                    label_1.setVisible(false);
                    label_2.setVisible(false);
                    label_3.setVisible(true);
                    label_4.setVisible(false);
                    label_5.setVisible(false);
                    checkmate = 2;
                    return;
                }
            }
        }
        System.out.println("c");
        label_1.setVisible(true);
        label_2.setVisible(false);
        label_3.setVisible(false);
        label_4.setVisible(false);
        label_5.setVisible(false);
        checkmate = 0;
        for (int num = 0; num<90; num++){
            qieces[num].setMoveof(0);
            qieces[num].setScl(0);
        }
    }

    public void swap(int A,int B,int i,int j){
        Qiece o = new Death(i+1,j+1);
        int a = qieces[A*9+B].getX();
        int b = qieces[A*9+B].getY();
        switch (qieces[i*9+j].getKind()){
            case 1 : {
                o = new General(qieces[i*9+j],0,qieces[i*9+j].getController());
                break;
            }
            case 2 : {
                o = new Assistant(qieces[i*9+j],0,qieces[i*9+j].getController());
                break;
            }
            case 3 : {
                o = new Minister(qieces[i*9+j],0,qieces[i*9+j].getController());
                break;
            }
            case 4 : {
                o = new Chariot(qieces[i*9+j],0,qieces[i*9+j].getController());
                break;
            }
            case 5 : {
                o = new Horse(qieces[i*9+j],0,qieces[i*9+j].getController());
                break;
            }
            case 6 : {
                o = new Cannon(qieces[i*9+j],0,qieces[i*9+j].getController());
                break;
            }
            case 7 : {
                o = new Soldier(qieces[i*9+j],0,qieces[i*9+j].getController());
                break;
            }
            default : {
                o = new Death(i, j);
            }
        }
        o.setX(a);
        o.setY(b);

        Qiece o2 = new Death(A+1,B+1);
        a = qieces[i*9+j].getX();
        b = qieces[i*9+j].getY();
        switch (qieces[A*9+B].getKind()){
            case 1 : {
                o2 = new General(qieces[A*9+B],0,qieces[A*9+B].getController());
                break;
            }
            case 2 : {
                o2 = new Assistant(qieces[A*9+B],0,qieces[A*9+B].getController());
                break;
            }
            case 3 : {
                o2 = new Minister(qieces[A*9+B],0,qieces[A*9+B].getController());
                break;
            }
            case 4 : {
                o2 = new Chariot(qieces[A*9+B],0,qieces[A*9+B].getController());
                break;
            }
            case 5 : {
                o2 = new Horse(qieces[A*9+B],0,qieces[A*9+B].getController());
                break;
            }
            case 6 : {
                o2 = new Cannon(qieces[A*9+B],0,qieces[A*9+B].getController());
                break;
            }
            case 7 : {
                o2 = new Soldier(qieces[A*9+B],0,qieces[A*9+B].getController());
                break;
            }
            default: {
                o2 = new Death(A, B);
            }
        }
        o2.setX(a);
        o2.setY(b);

        qieces[A*9+B] = o;
        qieces[i*9+j] = o2;
    }

    public void swap_1(int A,int B,int i,int j){
        Qiece o = new Death(i+1,j+1);
        int a = qieces[A*9+B].getX();
        int b = qieces[A*9+B].getY();
        System.out.println("k:"+k);
        switch (k){
            case 1 : {
                o = new General(qieces[i*9+j],0,1-index);
                break;
            }
            case 2 : {
                o = new Assistant(qieces[i*9+j],0,1-index);
                break;
            }
            case 3 : {
                o = new Minister(qieces[i*9+j],0,1-index);
                break;
            }
            case 4 : {
                o = new Chariot(qieces[i*9+j],0,1-index);
                break;
            }
            case 5 : {
                o = new Horse(qieces[i*9+j],0,1-index);
                break;
            }
            case 6 : {
                o = new Cannon(qieces[i*9+j],0,1-index);
                break;
            }
            case 7 : {
                o = new Soldier(qieces[i*9+j],0,1-index);
                break;
            }
            default : {
                o = new Death(i, j);
            }
        }
        o.setX(a);
        o.setY(b);

        Qiece o2 = new Death(A+1,B+1);
        a = qieces[i*9+j].getX();
        b = qieces[i*9+j].getY();
        switch (qieces[A*9+B].getKind()){
            case 1 : {
                o2 = new General(qieces[A*9+B],0,index);
                break;
            }
            case 2 : {
                o2 = new Assistant(qieces[A*9+B],0,index);
                break;
            }
            case 3 : {
                o2 = new Minister(qieces[A*9+B],0,index);
                break;
            }
            case 4 : {
                o2 = new Chariot(qieces[A*9+B],0,index);
                break;
            }
            case 5 : {
                o2 = new Horse(qieces[A*9+B],0,index);
                break;
            }
            case 6 : {
                o2 = new Cannon(qieces[A*9+B],0,index);
                break;
            }
            case 7 : {
                o2 = new Soldier(qieces[A*9+B],0,index);
                break;
            }
            default: {
                o2 = new Death(A, B);
            }
        }
        o2.setX(a);
        o2.setY(b);

        qieces[A*9+B] = o;
        qieces[i*9+j] = o2;
    }

}
